﻿//-----------------------------------------------------------------------
// <copyright file="ViewModelLocator.cs" company="WpfDevelopment.com">
//     Copyright WpfDevelopment.com. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace WpfDevelopment.MVVM
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Dynamic;

    /// <summary>
    /// used to locate view models in the ioc container
    /// </summary>
    public class ViewModelLocator : DynamicObject
    {
        /// <summary>
        /// Gets the <see cref="System.Object"/> at the specified index.
        /// This one can be used in Silverlight (the above is not supported in SL4)
        /// example: DataContext="{Binding [AboutViewModel], Source={StaticResource ViewModelLocator}}"
        /// </summary>
        /// <param name="index">the name of the member to check.</param>
        /// <returns>The viewmodel that was requested</returns>
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Guess code analysis doesn't understand it")]
        public object this[string index]
        {
            get { return IoC.Container.GetInstanceByName<object>(index); }
        }

        /// <summary>
        /// Provides the implementation for operations that get member values. 
        /// Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class 
        /// can override this method to specify dynamic behavior for operations such as getting a value for a property.
        /// This one can be used in WPF example: DataContext="{Binding AboutViewModel, Source={StaticResource ViewModelLocator}}"
        /// </summary>
        /// <param name="binder">Provides information about the object that called the dynamic
        /// operation. The binder.Name property provides the name of the member on which 
        /// the dynamic operation is performed. For example, for the 
        /// Console.WriteLine(sampleObject.SampleProperty) statement, where sampleObject
        /// is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class,
        /// binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether
        /// the member name is case-sensitive.</param>
        /// <param name="result">The result of the get operation. For example, if the method is
        /// called for a property, you can assign the property value to <paramref name="result"/>.</param>
        /// <returns>
        /// true if the operation is successful; otherwise, false. If this method returns false,
        /// the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.)
        /// </returns>
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Swallow exception and return null as in unable to find")]
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (binder == null)
            {
                throw new ArgumentNullException("binder");
            }

            try
            {
                result = IoC.Container.GetInstanceByName<object>(binder.Name);
                return true;
            }
            catch
            {
                result = null;
                return false;
            }
        }
    }
}
